# -*- coding: utf-8 -*-
from starlette.responses import JSONResponse
from sqlalchemy.ext.automap import automap_base
from fastapi import HTTPException
from application.config.mysql import engine
import datetime
import hmac
import requests
from application.utils.sm4 import SM4
import hashlib
import threading
import random
import queue
from application.config.redis import *
from datetime import datetime
from apps.log_config import setup_logging

AutoBase = automap_base()


# 自动化模型
def auto_model(table_name):
    AutoBase.prepare(engine, reflect=True)  # 刷新数据库连接
    try:
        orm = getattr(AutoBase.classes, str(table_name).strip())
    except:
        raise HTTPException(status_code=401, detail=f"'{table_name}'表不存在!")
    return orm


# 是否在活动开始时间
def is_start_time():
    current_time = datetime.datetime.now()
    start_time = datetime.datetime(2023, 7, 14, 10, 0, 0)
    end_time = datetime.datetime(2023, 7, 14, 22, 0, 0)
    if start_time <= current_time <= end_time:
        return True
    else:
        return False


# MD5加密
def md5_encrypt(string):
    md5 = hashlib.md5()  # 创建一个 MD5 对象
    md5.update(string.encode('utf-8'))  # 更新哈希对象以包含字符串
    encrypted_string = md5.hexdigest()  # 获取加密后的十六进制表示
    return encrypted_string


def get_encrypt_information(access_token, openid, signature):
    url = 'https://api.weixin.qq.com/wxa/business/getuserencryptkey'
    params = {
        'access_token': access_token,
        'openid': openid,
        'signature': signature,
        'sig_method': 'hmac_sha256'
    }
    response = requests.get(url, params=params)
    data = response.json()
    # data = {
    #     "errcode":0,#成功
    #     "errmsg":"ok",
    #     "key_info_list":
    #     [
    #         {
    #             "encrypt_key":"VI6BpyrK9XH4i4AIGe86tg==",
    #             "version":10,
    #             "expire_in":3597,
    #             "iv":"6003f73ec441c386",
    #             "create_time":1616572301
    #         },
    #         {
    #             "encrypt_key":"aoUGAHltcliiL9f23oTKHA==",
    #             "version":9,
    #             "expire_in":0,
    #             "iv":"7996656384218dbb",
    #             "create_time":1616504886
    #         },
    #     ]
    # }
    return data


# 验证是否加密
def verify_encryption(openid, access_token, request_time, secret_key, version):
    redis_db = connect_redis(0)
    session_key = str(redis_db.get(openid))
    signature = hmac.new(session_key.encode(), b'', hashlib.sha256).hexdigest()  # 跟php一致
    data = get_encrypt_information(access_token, openid, signature)
    if data['errcode'] != 0:
        return JSONResponse(content={'status': 0, 'message': '第三方网络请求错误', 'data': data}, status_code=403)
    encrypt_key = next((i['encrypt_key'] for i in data['key_info_list'] if i['version'] == version), '')
    md5_str = md5_encrypt(openid + request_time + encrypt_key)
    if md5_str != secret_key:
        return JSONResponse(content={'status': 0, 'message': '不合法的请求', 'data': None}, status_code=405)


def get_openid(js_code):
    url = "https://api.weixin.qq.com/sns/jscode2session"
    # params = {  # 一汽丰田小程序
    #     "js_code": js_code,  # "0d10FwFa1g0uyF02MnJa19Ix9l40FwF6"
    #     "grant_type": "authorization_code",
    #     "appid": "wx2cbba5931ada9e5d",
    #     "secret": "0d440eedd1a829cf563a3a27d9d523c8",
    # }
    params = {  # 一c小程序
        "js_code": js_code,  # "0d10FwFa1g0uyF02MnJa19Ix9l40FwF6"
        "grant_type": "authorization_code",
        "appid": "wx9adbf602b47906c2",
        "secret": "72764c203f6ba16e399ad4cedb60dd8e",
    }

    response = requests.get(url, params=params)
    data = response.json()
    # data = {
    #     "session_key": "WD3AarpeyM/Vajl7/qIMBQ==",
    #     "openid": "ok9HS5Shggvu6AUSIyz8jQQ_QX6k"
    # }
    return data


def get_phone(access_token, code):
    url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
    data = {
        "code": code
    }
    params = {
        "access_token": access_token
    }
    response = requests.post(url, params=params, json=data)
    data = response.json()
    return data


# 抽奖概率
def lottery_draw(probability):
    # 判断获奖人员是否符合抽奖概率
    if random.random() <= probability:
        return True
    else:
        return False


# 奖品中奖、未中奖人数统计
def zw_count(num_db, prize_id):
    if redis_exists(num_db, prize_id):
        w_count = int(redis_get(num_db, prize_id)) + 1
        redis_set3day(num_db, prize_id, w_count)
    else:
        redis_set3day(num_db, prize_id, 1)


# 答题总人数
def an_count(num_db, answer_count):
    if redis_exists(num_db, answer_count):
        a_count = int(redis_get(num_db, answer_count)) + 1
        redis_set3day(num_db, answer_count, a_count)
    else:
        redis_set3day(num_db, answer_count, 1)


# 抽奖总人数
def dp_count(num_db, draw_prize_count):
    if redis_exists(num_db, draw_prize_count):
        a_count = int(redis_get(num_db, draw_prize_count)) + 1
        redis_set3day(num_db, draw_prize_count, a_count)
    else:
        redis_set3day(num_db, draw_prize_count, 1)


# openid加密  16位大写
def openid_uuid(openid):
    original_str = SM4(openid).add_secret()
    openid_jm_h10 = hashlib.md5(original_str.encode('utf-8')).hexdigest().upper()[:10]
    openid_h4 = openid[-4:]
    uuid = 'M' + str(openid_h4) + 'M' + openid_jm_h10
    return uuid


# 卡券创建
def coupons_create(access_token, json):
    url = 'https://api.weixin.qq.com/card/create'
    data = {
        "card": {
            "card_type": "MEETING_TICKET",
            "meeting_ticket": {
                "base_info": {
                    "logo_url": "http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0",
                    "brand_name": "一汽丰田",
                    "code_type": "CODE_TYPE_TEXT",
                    "title": "2024春节优惠券",
                    "color": "Color010",
                    "notice": "使用时向检票员出示此券",
                    "description": "请务必准时入场",
                    "date_info": {
                        "type": 1,
                        "begin_timestamp": 1706284800,
                        "end_timestamp": 1706630400
                    },
                    "sku": {
                        "quantity": 50000000
                    },
                    "get_limit": 3,
                    "use_custom_code": True,
                    "bind_openid": False,
                    "can_share": False,
                    "can_give_friend": False,
                    "location_id_list": [
                        123,
                        12321,
                        345345
                    ],
                    "custom_url_name": "查看更多",
                    "custom_url": "http://www.qq.com",
                    "custom_url_sub_title": "门店了解详情"
                },
                "meeting_detail": "进入门店了解详情"
            }
        }
    }
    params = {
        'access_token': access_token,
    }
    data_text = json.dumps(data, ensure_ascii=False).encode('utf-8')
    response = requests.post(url, params=params, data=data_text)
    data = response.json()
    return data


jm_list = [
    'BcP3dr',
    'akn6we',
    'mHb4we',
    'CSers3',
    'awaQFe',
    'sfFEGg',
    'FSsfeF',
    'sfenx1',
    'sEDdw2'
]

import time
from application.utils.get_api_ticket import redis_api_ticket
from apps.frontapp.signature import get_all_signature


# 添加微信单个卡包
def add_card(yf_code, card_id):
    try:
        timestamp = int(time.time())
        # yf_code = '123'  # yf卡号
        # card_id = 'pWIrjjt2ugZ68xjFLglm-2K6HeAw'
        nonce_str = str(random.randrange(1000000)).zfill(6)  # 随机
        api_ticket = redis_api_ticket()
        signature = get_all_signature(timestamp, yf_code, card_id, str(nonce_str), api_ticket)
        data = {
            'timestamp': timestamp,
            'yf_code': yf_code,
            'card_id': card_id,
            'nonce_str': nonce_str,
            'api_ticket': api_ticket,
            'signature': signature
        }
        return data
    except:
        return False


def yf_token():
    # 测试地址-------------------------------------------------------------------------
    # url = 'https://bp-testing.ftms.com.cn/uat/ftms-business-platform-user/access-token'
    # data = {
    #     "operatorId": "FTMS",
    #     "operatorName": "李四",
    #     "secretKey": "b1b8f1b7cb43853a05127e931659d595535e57f7715706d49d3fa1ff59f647fd"
    # }
    # 正式地址--------------------------------------------------------------------------
    url = 'https://bp.ftms.com.cn/ftms-business-platform-user/access-token'
    data = {
        "operatorId": "2024CNYWeChat",
        "operatorName": "2024WeChatMoments",
        "secretKey": "89c8ebf1869b93bcf2468cf6878413b67d8d0747aa215b42aa200ba02ed423e33ff7252805ca4dd363a18ae9f1ceec5b029fa3adc351bf2dae181862f518877a"
    }
    response = requests.post(url, json=data)
    if response.status_code == 200:
        data = response.json()
        # yf_access_token = data['accessToken']
        return data
    else:
        return False


# 获取redis中的yf_redis_access_token
def yf_redis_access_token():
    if redis_exists(1, 'yf_access_token'):
        return redis_get(1, 'yf_access_token').decode('utf-8')
    else:
        yf_access_token = yf_token()['accessToken']  # 生成新的accessToken
        redis_set(1, 3600, 'yf_access_token', yf_access_token)  # 过期时间3600秒
        return yf_access_token


info_logger, error_logger = setup_logging()


# 领取卡券
def yf_car_code(token, couponId, phone, dealerCode, modelId):
    current_time = datetime.now()
    formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
    # 测试地址-------------------------------------------------------------------------
    # url = 'https://bp-testing.ftms.com.cn/uat/ftms-business-platform-coupon/unregister-user-coupons'
    # data = {
    #     "couponId": couponId,  # 开放卡券类型id
    #     "dealerCode": dealerCode,  # 经销商id
    #     "mobile": phone,  # 用户手机号
    #     "modelId": modelId,  # 车型id
    #     "receiveTime": formatted_time,  # 提交时间
    #     "thirdpartyReceiveChannel": "TAOBA0",  # 第三方来源
    #     "userMobile": "13021083001",
    #     "userName": "路飞"
    # }
    # 正式地址--------------------------------------------------------------------------
    url = 'https://bp.ftms.com.cn/ftms-business-platform-coupon/unregister-user-coupons'
    data = {
        "couponId": couponId,  # 开放卡券类型id
        "dealerCode": dealerCode,  # 经销商id
        "mobile": phone,  # 用户手机号
        "modelId": modelId,  # 车型id
        "receiveTime": formatted_time,  # 提交时间
        "thirdpartyReceiveChannel": "2024年春节抖音红包CNY活动-微信朋友圈",  # 第三方来源
        "userMobile": phone,
        "userName": "2024WeChatMoments",
        "operatorId": "2024CNYWeChat"
    }
    headers = {
        'authorization': 'Bearer ' + str(token),
    }
    try:
        response = requests.post(url, headers=headers, json=data)
        info_logger.info('领取卡券_参数' + str(data) + '响应' + str(response.json()))
        if response.status_code == 200:
            data = response.json()
            redeemCode = data['redeemCode']
            return redeemCode
        else:
            return None
    except Exception as e:
        error_logger.error("领取卡券失败_参数" + str(data) + '原因' + str(e))
        return None


# # 投放卡券函数
# def for_add_card(phone, dealerCode):
#     try:
#         car_list = {
#             824: 'pWIrjjtqrIy9NmJojK9aHfm4tPuc',
#             825: 'pWIrjjl8bu43_nLMi1D9ozACimTU',
#             826: 'pWIrjjh5Y1jbBV0cZPUeP0VsP0pA',
#             827: 'pWIrjjqLrC1F5BclkwK6tBn7ipg8',
#             828: 'pWIrjju3BQ_OOp8J4rEJp5nTI97Q',
#             # 888: 'pWIrjjk_OQs5bQ06PprveOpFyYwE',  # 第六种情况特殊
#         }
#         yf_code_list = []
#         for k, v in car_list.items():
#             if k == 824:
#                 modelId = 33
#             elif k == 825:
#                 modelId = 59
#             elif k == 826:
#                 modelId = 55
#             elif k == 827:
#                 modelId = 57
#             elif k == 828:
#                 modelId = 62
#             elif k == 888:
#                 sj = [55, 59, 62]
#                 modelId = random.choice(sj)
#             else:
#                 modelId = 55
#             yf_code = yf_car_code(yf_redis_access_token(), k, phone, dealerCode, modelId)
#             sj_str = yf_code if yf_code else str(random.randrange(1000000000000)).zfill(12)
#             vx_card = add_card(sj_str, v)
#             if vx_card:
#                 yf_code_list.append(vx_card)
#         return yf_code_list
#     except:
#         return False


# # 投放卡券函数_多线程
def for_add_card(phone, dealerCode):
    car_list = { #一汽丰田备份
        824: 'pWIrjjtqrIy9NmJojK9aHfm4tPuc',
        825: 'pWIrjjl8bu43_nLMi1D9ozACimTU',
        826: 'pWIrjjh5Y1jbBV0cZPUeP0VsP0pA',
        827: 'pWIrjjqLrC1F5BclkwK6tBn7ipg8',
        828: 'pWIrjju3BQ_OOp8J4rEJp5nTI97Q',
        832: 'pWIrjjk_OQs5bQ06PprveOpFyYwE',  # 第六种情况特殊
    }
    # car_list = {  # 一C
    #     824: 'pPNyT1B9GBtInmZWlLrokdi84q7g',
    #     825: 'pPNyT1PhxmSgrCAlz0si7Hi2J7xY',
    #     826: 'pPNyT1BGD6uEpwCHNEXmcE4nMH9Y',
    #     827: 'pPNyT1B7N30NCwaJjjVn6AcJmpKE',
    #     828: 'pPNyT1Jsc8ItxySwpkNx3pit4iEc',
    #     832: 'pPNyT1BvlThGpmfUV0mYCnRojkp0',  # 第六种情况特殊
    # }

    def add_card_task(k, v, phone, dealerCode, result_queue):
        try:
            if k == 824:
                modelId = 33
            elif k == 825:
                modelId = 59
            elif k == 826:
                modelId = 55
            elif k == 827:
                modelId = 57
            elif k == 828:
                modelId = 62
            elif k == 832:
                sj = [55, 59, 62]
                modelId = random.choice(sj)
            else:
                modelId = 55
            yf_code = yf_car_code(yf_redis_access_token(), k, phone, dealerCode, modelId)
            sj_str = yf_code if yf_code else str(random.randrange(1000000000000)).zfill(12)
            vx_card = add_card(sj_str, v)
            if vx_card:
                result_queue.put(vx_card)
        except Exception as e:
            print(f"Error processing card {k}: {e}")

    threads = []
    result_queue = queue.Queue()

    for k, v in car_list.items():
        thread = threading.Thread(target=add_card_task, args=(k, v, phone, dealerCode, result_queue))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

    yf_code_list = []
    while not result_queue.empty():
        yf_code_list.append(result_queue.get())

    return yf_code_list


def go_check_code(openid, phone):
    processed_phone = phone[:3] + '****' + phone[-4:]
    last_six_of_a = openid[-6:]
    check_code = processed_phone + '_' + last_six_of_a
    return check_code


# 存抽奖结果
def save_redis(openid, new_dic):
    uuid = openid_uuid(openid)
    last_digit = uuid[-1]
    redis_key_map = {
        '0': 14, '1': 14, '2': 14,
        '3': 15, '4': 15, '5': 15,
        '6': 16, '7': 16, '8': 16,
        '9': 17, 'A': 17, 'B': 17,
        'C': 18, 'D': 18,
        'E': 19, 'F': 19
    }
    redis_json_permanent(redis_key_map.get(last_digit), openid, new_dic)


def get_redis(openid):
    uuid = openid_uuid(openid)
    last_digit = uuid[-1]
    redis_key_map = {
        '0': 14, '1': 14, '2': 14,
        '3': 15, '4': 15, '5': 15,
        '6': 16, '7': 16, '8': 16,
        '9': 17, 'A': 17, 'B': 17,
        'C': 18, 'D': 18,
        'E': 19, 'F': 19
    }
    an_dic = redis_json_get(redis_key_map.get(last_digit), openid)
    return an_dic
